package com.kob.backend.controller.car;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kob.backend.pojo.AuctionTask;
import com.kob.backend.pojo.Car;
import com.kob.backend.pojo.TaskObj;
import com.kob.backend.service.auction.AuctionTaskService;
import com.kob.backend.service.car.CarService;
import com.kob.backend.vo.AuctionTaskVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.*;

/**
 * @program: backend
 * @description:
 * @author: mqf
 * @create: 2023-03-21 19:46
 **/
@RestController
@RequestMapping("/car")
@Slf4j
public class CarController {

    @Autowired
    CarService carService;
    @Autowired
    AuctionTaskService auctionTaskService;

    /**
     * @param map 包含小车id，taskname
     * @return
     * @throws MalformedURLException
     */
    @PostMapping("/sendTask")
    public Map<String, String> sendTask(@RequestParam Map<String, String> map) throws MalformedURLException {
        String taskName = map.get("taskName");//需要根据id判断,当前前端只能输入task1、task2....五位字符，需要修改小车py代码的接收逻辑
        int id = Integer.parseInt(map.get("id"));

        String auctionId = map.get("auctionId");

        LambdaQueryWrapper<AuctionTask> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AuctionTask::getAuctionId, auctionId);
        List<AuctionTask> list = auctionTaskService.list(lambdaQueryWrapper);
        Car car = carService.getById(id);

        for (int i = 0; i < list.size(); i++) {
            AuctionTask auctionTask = list.get(i);
            float evToRsu = Float.parseFloat(auctionTask.getEvToRsu());
            int photoNumber = (int) (evToRsu * 10);
            car.setPhotoNumber(photoNumber);
            carService.updateById(car);
        }
        // 完成时间 衡量通信协议
        // energy
        // 通信开销

        String ip = car.getIp();
        int port = car.getPort();
        String path = "/task";
        Map<String, String> params = new HashMap<>();
        params.put("op", taskName);
        carService.doPost(ip, port, path, params);
        log.info("continue");//
        Map<String, String> res = new HashMap<>();

        res.put("error_message", "success");
        return res;
    }

    boolean bigger(String a, String b) {
        return Float.parseFloat(a) > Float.parseFloat(b);
    }

    @PostMapping("/judge")
    public Map<String, String> judgeExecuteTask(@RequestParam Map<String, String> map) throws MalformedURLException {
        // 小车id， auction_task的id, execute表示是否执行：yes or no
        Map<String, String> res = new HashMap<>();

        String carId = map.get("carId");
        String taskId = map.get("taskId");
        String execute = map.get("execute");
        AuctionTaskVo vo = auctionTaskService.getOneById(Integer.valueOf(taskId));

        // 不接受
        if ("no".equals(execute)) {
            res.put("error_message", "success");
            res.put("msg", "refuse the task");
            return res;
        }
        // 余额不足
        if (!bigger(carService.getEnergyById(Integer.valueOf(carId)), vo.getCost())) {
            res.put("error_message", "success");
            res.put("msg", "energy lack");
            return res;
        }
        // 接收任务， 目前只有拍照任务

        String evToRsu = vo.getEvToRsu();
        List<TaskObj> tasks = vo.getTasks();
        float number = 0;
        for (TaskObj obj : tasks) {
            if (obj.getPropertyName().equals("number")) {
                number = obj.getPropertyValue();
            }
        }
        number = number * Float.parseFloat(evToRsu);
        Car car = carService.getById(Integer.parseInt(carId));
        car.setPhotoNumber((int) number);
        carService.updateById(car);
        // 车的具体信息
        String ip = car.getIp();
        int port = car.getPort();
        String path = "/task";
        Map<String, String> params = new HashMap<>();
        //get0即为任务1的相关信息，其id为1
        params.put("op", "task" + tasks.get(0).getTaskId());
        long start = System.currentTimeMillis();//小车开始执行任务时间戳
        System.out.println("start:" + start);
        start = start / 1000;
        //通信开销在此处产生
        String msg = carService.doPost(ip, port, path, params);


        if (msg == null || msg.isEmpty()) {
            res.put("error_message", "success");
            res.put("msg", "car do not execute the task..");
            return res;
        }
        // Long end = Long.valueOf(msg);//小车结束任务时间戳
        String[] splitStr = msg.split(" ");
        String end1 = splitStr[0];
        String end2 = splitStr[1];
        Long endTransform = Long.valueOf(end1.substring(0, msg.indexOf('.')));
        Long endTask = Long.valueOf(end2.substring(0, msg.indexOf('.')));
        System.out.println("end:" + endTransform + ";start:" + start);
        String timeDelay = String.valueOf(endTransform - start);
        String taskConsume = String.valueOf(endTask - start);

        System.out.println("timedelay:" + timeDelay + " taskConsume:" + taskConsume);
        System.out.println(msg);
        // 消耗能量
        carService.changeEnergy(Integer.valueOf(carId), "-" + vo.getCost());
        // rsu给ev能量
        carService.changeEnergy(Integer.valueOf(carId), String.valueOf(Float.parseFloat(vo.getRsuToEv()) * 100));

        res.put("error_message", "success");
        res.put("msg", String.format("energy %s %s", "-" + vo.getCost(),
                "+" + Float.parseFloat(vo.getRsuToEv()) * 100));
        //res.put("time_delay", timeDelay);
        res.put("task_consume", taskConsume);//返回秒值
        return res;
    }


    /**
     * 需要接收map，map内为id，ip，port
     * 根据id对数据库中的ip和port进行修改
     *
     * @param map 包含 id，ip，port
     * @return map(error_message, success)
     */
    @PostMapping("/updateIp")
    public Map<String, String> updateIp(@RequestParam Map<String, String> map) {
        int id = Integer.parseInt(map.get("id"));
        String ip = map.get("ip");
        int port = Integer.parseInt(map.get("port"));
        Car car = carService.getById(id);
        car.setIp(ip);
        car.setPort(port);
        carService.updateById(car);
        Map<String, String> res = new HashMap<>();
        res.put("error_message", "success");
        return res;
    }

    private int getPos(String key) {
        int pos = key.indexOf(".");
        return Integer.parseInt(key.substring(0, pos));
    }

    @GetMapping("/getAndSave")
    public void getAndSave(@RequestParam Map<String, String> map) {
        String projectRoot = System.getProperty("user.dir");
        String imgDirectory = projectRoot + File.separator + "images";
        String carName = map.get("carName");
        LambdaQueryWrapper<Car> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Car::getCarName, carName);
        Car car = carService.getOne(lambdaQueryWrapper);

        String bucketName = car.getPacketName();
        String endpoint = "oss-cn-chengdu.aliyuncs.com";
        String accessKeyId = "LTAI5tEwwSBita9Y9GLePsMa";
        String accessKeySecret = "hJvKLmKaae9urXl3pjjuGjnIbviW2d";
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        int imgIdx = 1;
        boolean continueDownload = true;
        Instant lastIterationTime = Instant.now();
        while (continueDownload) {
            String ObjectName = imgIdx + ".jpg";
            String saveName = imgDirectory + File.separator + imgIdx + ".jpg";
            // 创建File对象
            File dir = new File(imgDirectory);
            // 如果目录不存在，就创建它
            if (!dir.exists()) {
                dir.mkdirs();
            }
            try {
                ossClient.getObject(new GetObjectRequest(bucketName, ObjectName), new File(saveName));
                lastIterationTime = Instant.now();
            } catch (com.aliyun.oss.ClientException e) {
                // System.out.println("error msg: " + e.getMessage());
                Instant currentTime = Instant.now();
                Duration timeElapsed = Duration.between(lastIterationTime, currentTime);
                if (timeElapsed.getSeconds() >= 5) {
                    System.out.println("识别结束！");
                    continueDownload = false;
                }
            }
            imgIdx++;
        }
    }

    /**
     * 接收carName，返回图片url
     */
    @GetMapping("/getPhoto")
    public Map<String, Object> getPhoto(@RequestParam Map<String, String> map) throws MalformedURLException {
        String carName = map.get("carName");
        LambdaQueryWrapper<Car> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Car::getCarName, carName);
        Car car = carService.getOne(lambdaQueryWrapper);
        int photoNumber = car.getPhotoNumber();

        String bucketName = car.getPacketName();
        String endpoint = "oss-cn-chengdu.aliyuncs.com";
        String accessKeyId = "LTAI5tEwwSBita9Y9GLePsMa";
        String accessKeySecret = "hJvKLmKaae9urXl3pjjuGjnIbviW2d";
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        ObjectListing objectListing = ossClient.listObjects(bucketName);
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        List<OSSObjectSummary> res = new ArrayList<>();
        for (OSSObjectSummary oos : sums) {
            if (oos.getKey().endsWith(".jpg")) res.add(oos);
        }
        long totalSize = 0;
        res.sort(Comparator.comparingInt(o -> getPos(o.getKey())));
        DecimalFormat df = new DecimalFormat("#.00KB");

        ossClient.shutdown();
        //https://packethyh.oss-cn-chengdu.aliyuncs.com/1.jpg
        String str1 = "https://";
        String str2 = ".oss-cn-chengdu.aliyuncs.com/";
        String str3 = ".jpg";
        List<URL> urls = new ArrayList<>();
        List<String> sizes = new ArrayList<>();
        for (int i = 1; i <= photoNumber; i++) {
            String urlStr = str1 + bucketName + str2 + i + str3;
            URL url = new URL(urlStr);
            urls.add(url);
            totalSize += res.get(i).getSize();
            String size = df.format((double) res.get(i).getSize() / 1024);
            sizes.add(size);
            System.out.println(i + ".jpg" + " -> " + size);
        }
        String tot = df.format((double) totalSize / 1024);
        Map<String, Object> result = new HashMap<>();
        result.put("list", urls);
        result.put("sizes", sizes);
        result.put("totalSize", tot);
        return result;
    }

    @GetMapping("/list")
    public List<Car> getCarList() {
        return carService.list();
    }

    @PostMapping("/updateOrSave")
    public Map<String, Object> updateOrSave(@RequestBody Car car) {
        boolean b = carService.saveOrUpdate(car);
        Map<String, Object> map = new HashMap<>();
        map.put("msg", b ? "success" : "failed");
        return map;
    }

    @PostMapping("/energy")
    public Map<String, Object> changeEnergy(@RequestParam Map<String, String> map) {
        String id = map.get("id");
        String offset = map.get("offset");

        boolean b = carService.changeEnergy(Integer.parseInt(id), offset);
        Map<String, Object> res = new HashMap<>();
        res.put("msg", b ? "success" : "failed");
        return res;
    }

    @GetMapping("/energy")
    public String getEnergy(@RequestParam Map<String, String> map) {
        return carService.getEnergyById(Integer.valueOf(map.get("id")));
    }

    /**
     * 根据id选择更新哪辆车的电量 测试更新git
     *
     * @param map
     * @throws ClientException
     * @throws IOException
     */
    @GetMapping("/readenergy")
    public void readEnergy(@RequestParam Map<String, String> map) throws ClientException, IOException {
        String id = map.get("id");
        carService.readEnergy(id);
    }

    /**
     * 更新小车电量
     *
     * @param map
     */
    @GetMapping("/sendtask2")
    public void sendTask2(@RequestParam Map<String, String> map) throws MalformedURLException {
        int id = Integer.parseInt(map.get("id"));
        Car car = carService.getById(id);
        String ip = car.getIp();
        int port = car.getPort();
        String path = "/task";
        Map<String, String> params = new HashMap<>();
        params.put("op", "GetPower");
        String res = carService.doPost(ip, port, path, params);
        //int power = Integer.parseInt(res);
        car.setEnergy(res);
        carService.save(car);
        System.out.println(res);

    }
}
